#pragma once
#include "HashBucket.h"

namespace My_unordered_set
{
	template<class K, class Hash = HashFunc<K>>
	class unordered_set
	{
		struct SetKeyOfT
		{
			const K& operator()(const K& key)
			{
				return key;
			}
		};
	public:
		typedef typename Hash_Bucket::HashTable<K, const K, SetKeyOfT, Hash>::Iterator iterator;
		typedef typename Hash_Bucket::HashTable<K, const K, SetKeyOfT, Hash>::ConstIterator const_iterator;
		unordered_set() = default;
		unordered_set(initializer_list<K> il)
		{
			for (const auto& e : il)
			{
				_ht.Insert(e);
			}
		}
		template<class InputIterator>
		unordered_set(InputIterator first, InputIterator last)
		{
			while (first != last)
			{
				_ht.Insert(*first);
				++first;
			}
		}
		unordered_set(const unordered_set& x)
		{
			for (const auto& e : x)
			{
				_ht.Insert(e);
			}
		}
		unordered_set& operator=(const unordered_set& x)
		{
			_ht = x._ht;
			return *this;
		}
		pair<iterator,bool> insert(const K& key)
		{
			return _ht.Insert(key);
		}
		bool erase(const K& key)
		{
			return _ht.Erase(key);
		}
		iterator begin()
		{
			return _ht.Begin();
		}
		iterator end()
		{
			return _ht.End();
		}
		const_iterator begin() const
		{
			return _ht.Begin();
		}
		const_iterator end() const
		{
			return _ht.End();
		}
		iterator find(const K& key)
		{
			return _ht.Find(key);
		}
		size_t size() const
		{
			return _ht.Size();
		}
		bool empty() const
		{
			return _ht.Empty();
		}
		size_t count(const K& key)
		{
			return _ht.Count(key);
		}
		size_t bucket_count()
		{
			return _ht.Bucket_count();
		}
		size_t bucket_size(const K& key)
		{
			return _ht.Bucket_size(key);
		}
	private:
		Hash_Bucket::HashTable<K, const K, SetKeyOfT, Hash> _ht;
	};
	void test1_set()
	{
		unordered_set<int> st;
		st.insert(1);
		st.insert(2);
		st.insert(3);
		st.insert(54);
		st.insert(55);
		unordered_set<int>::const_iterator it = st.begin();
		while (it != st.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;
		/*for (auto& e : st)
		{
			cout << e << " ";
		}
		cout << endl;*/
	}
	void test2_set()
	{
		unordered_set<int> st;
		st.insert(1);
		st.insert(2);
		st.insert(3);
		st.insert(54);
		st.insert(55);
		unordered_set<int>::const_iterator it = st.begin();
		while (it != st.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;
		cout << st.empty() << endl;
		cout << st.size() << endl;
		cout << st.bucket_count() << endl;
		if (st.count(54)) {
			cout << st.bucket_size(54) << endl;
		}
	}
	void test3_set()
	{
		unordered_set<int> st = { 1,2,3,55,54 };
		unordered_set<int>::const_iterator it = st.begin();
		while (it != st.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;
		unordered_set<int> st1 = st;
		st1.insert(100);
		it = st1.begin();
		while (it != st1.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;

		st = st1;
		it = st.begin();
		while (it != st.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl << endl;
	}
}